package keter.framework.web.upload;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import keter.framework.exception.KeterFileException;
import keter.framework.model.FileItem;
import keter.framework.util.IOUtil;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import com.jfinal.kit.PropKit;

public class UploadUtil {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = LoggerFactory.getLogger(UploadUtil.class);
	private static String storeRoot = PropKit.get("upload.path");
	
	/**
	 * <p>Method ：makeDownload
	 * <p>Description : 文件下载通用方法
	 * @param request
	 * @param response
	 * @param localFileUri    本地文件地址
	 * @param fileName       (返回给浏览器的)文件名称
	 * @throws IOException 
	 * @author  gulixing@msn.com
	 * @version 1.0.0
	 * @throws KeterFileException 
	 */
	public static void makeDownload(HttpServletRequest request,
			HttpServletResponse response, FileItem fi) throws KeterFileException,
			IOException {
		response.setContentType("text/html;charset=UTF-8");
		request.setCharacterEncoding("UTF-8");
		String localFileUri = findUriByFileItem(fi);
		long fileLength = new File(localFileUri).length();
		if (fileLength == 0) {
			logger.error("文件id={},name={}不存在或已被删除！", fi.get("fileId"), fi.get("name"));
			throw new KeterFileException("下载请求的资源无法访问！", "该文件不存在或已被删除。");
		}
		String contentType = "application/octet-stream";
		response.setContentType(contentType);
		response.setHeader("Content-disposition", "attachment; filename="
				+ processFileName(request, fi.getStr("name")));
		response.setHeader("Content-Length", String.valueOf(fileLength));
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		bis = new BufferedInputStream(new FileInputStream(localFileUri));
		try {
			bos = new BufferedOutputStream(response.getOutputStream());
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (IOException e) {
			logger.error("下载文件处理异常",e);
		} finally{
			bis.close();
		    bos.close();
		}
	}
	
	/**
	 * <p>Method ：findFileUriByFileItem
	 * <p>Description : 根据fileItem内容在磁盘上找到对应文件的uri
	 * @param fi
	 * @return 
	 * @author  gulixing@msn.com
	 * @version 1.0.0
	 */
	public static String findUriByFileItem(FileItem fi){
		return storeRoot + File.separator + fi.get("path") + File.separator + fi.get("fileId");
	}
	
	/**
	 * <p>Method ：processFileName
	 * <p>Description : 识别浏览器类型，避免文件名中文乱码问题
	 * @param request
	 * @param fileName
	 * @return
	 * @throws UnsupportedEncodingException 
	 * @author  gulixing@msn.com
	 * @version 1.0.0
	 */
	private static String processFileName(HttpServletRequest request,String fileName) throws UnsupportedEncodingException{
		String agent = (String)request.getHeader("USER-AGENT");    
		String enableFileName=fileName;
		if(agent != null && !agent.contains("MSIE")) {// FF      
		    enableFileName = "=?UTF-8?B?" + (new String(Base64.encodeBase64(fileName.getBytes("UTF-8")))) + "?=";    
		} else { // IE      
		    enableFileName = new String(fileName.getBytes("GBK"), "ISO-8859-1");    
		} 
		return enableFileName;
	}
	
	/**
	 * <p>Method ：validateUploadFile
	 * <p>Description : 功能描述
	 * @param file
	 * @param ext    扩展名
	 * @param size   文件大小
	 * @param model
	 * @return 
	 * @author  gulixing@msn.com
	 * @version 1.0.0
	 * @throws KeterFileUploadException 
	 */
	public static void validateUploadFile(MultipartFile file,String extAllow,Long size) throws KeterFileException{
		String fileName = file.getOriginalFilename();
//		String ext = fileName.substring(fileName.lastIndexOf(".")+1,fileName.length());
		String ext = StringUtils.substringAfterLast(fileName, ".");
        if(!extAllow.contains(ext)){
        	throw new KeterFileException("上传失败：非法的文件格式:[ "+ext+" ]！");
        }
        if (file.getSize() > size) {
        	throw new KeterFileException("上传失败：文件大小超过限制！");
        }
	}
	
	
	/**
	 * <p>Method ：writeRandomNameFile
	 * <p>Description : 使用随机名称将文件写入upload.path下的子目录
	 * @param subFolder
	 * @param inputStream
	 * @return
	 * @throws IOException 
	 * @author  gulixing@msn.com
	 * @version 1.0.0
	 */
	public  static String writeRandomNameFile(String subFolder,InputStream inputStream) throws IOException{
		String fileId =  UUID.randomUUID().toString();
        //文件写入地址由3部分组成：Web目录 + 存储相对目录 + 伪文件名(使用统一的文件名保证重复上传时只存在一个文件)
    	String fileUri = IOUtil.ensureExists(storeRoot+File.separator+subFolder)+ File.separator + fileId;    	
        logger.info("写入文件:{},文件原名:{}", fileUri);
        Files.write(ByteStreams.toByteArray(inputStream), new File(fileUri));
        return fileId;
    }
	
	/**
	 * <p>Method ：writeRandomNameFile
	 * <p>Description : 使用随机名称将文件写入upload.path目录
	 * @param inputStream
	 * @throws IOException 
	 * @author  gulixing@msn.com
	 * @version 1.0.0
	 */
	public  static String  writeRandomNameFile(InputStream inputStream) throws IOException{
		return writeRandomNameFile("",inputStream);
	}
	
	
//	/**
//	 * <p>Method ：translateStatus
//	 * <p>Description : 将status进行转码处理
//	 * @param r 
//	 * @author  gulixing@msn.com
//	 * @version 1.0.0
//	 */
//	public static void translateStatus(CodeListService service,BasePaper bp){
//		Map<String, String>map = service.findByCodeKind("AUDIT-STATUS");
//		bp.setStatus(map.get(bp.getStatus()));
//	}
}
